package com.dianrong.common.uniauth.cas.handler;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.security.auth.login.AccountLockedException;
import javax.security.auth.login.AccountNotFoundException;
import javax.security.auth.login.CredentialExpiredException;
import javax.servlet.http.HttpSession;

import org.jasig.cas.authentication.AuthenticationException;
import org.springframework.binding.message.MessageBuilder;
import org.springframework.binding.message.MessageContext;
import org.springframework.webflow.execution.Event;

import com.dianrong.common.uniauth.cas.exp.FreshUserException;
import com.dianrong.common.uniauth.cas.exp.UserPasswordNotMatchException;
import com.dianrong.common.uniauth.cas.model.CasLoginCaptchaInfoModel;
import com.dianrong.common.uniauth.cas.util.WebScopeUtil;
import com.dianrong.common.uniauth.common.util.StringUtil;

/**
 * . cas用户登陆的验证码验证帮助类.
 * 
 * @author wanglin
 *
 */
public class CasUserLoginCaptchaValidHelper {
    /**
     * . 处理失败的id列表
     */
    private static final List<String> FAILAURE_EVENT_ID_LSIT = new ArrayList<String>();

    /**
     * . 处理失败的需要关注的异常class对象列表
     */
    private static final List<Class<? extends Exception>> FAILAURE_FOCUS_CLASS_LSIT = new ArrayList<Class<? extends Exception>>();

    /**
     * . 需要当做正常登陆成功处理的异常列表
     */
    private static final List<Class<? extends Exception>> FAILAURE_CLASS_AS_SUCCESS_LSIT = new ArrayList<Class<? extends Exception>>();

    /**
     * . 处理成功的id的列表
     */
    private static final List<String> SUCCESS_EVENT_ID_LSIT = new ArrayList<String>();

    /**
     * . 静态数据初始化
     */
    static {
        // 处理失败
        FAILAURE_EVENT_ID_LSIT.add("authenticationFailure");

        // 初始化异常class对象
        FAILAURE_FOCUS_CLASS_LSIT.add(AccountNotFoundException.class);
        FAILAURE_FOCUS_CLASS_LSIT.add(AccountLockedException.class);
        FAILAURE_FOCUS_CLASS_LSIT.add(UserPasswordNotMatchException.class);

        // 当做成功处理的异常
        FAILAURE_CLASS_AS_SUCCESS_LSIT.add(FreshUserException.class);
        FAILAURE_CLASS_AS_SUCCESS_LSIT.add(CredentialExpiredException.class);

        // 处理成功
        SUCCESS_EVENT_ID_LSIT.add("success");
        SUCCESS_EVENT_ID_LSIT.add("successWithWarnings");
        SUCCESS_EVENT_ID_LSIT.add("warn");
    }

    /**
     * . 进行登陆处理前的验证处理.
     * 
     * @param session httpSession
     * @param messageContext 国际化上下文
     * @param captcha 前端传入的验证码(可能为空,不需要验证码的情况)
     * @return 是否继续进行登陆处理
     */
    public boolean captchaValidProcessBefore(HttpSession session, final MessageContext messageContext, String captcha) {
        if (session != null) {
            CasLoginCaptchaInfoModel casCaptchaObj = WebScopeUtil.getCaptchaInfoFromSession(session);
            if (casCaptchaObj == null) {
                // 新设置一个
                WebScopeUtil.putCaptchaInfoToSession(session, new CasLoginCaptchaInfoModel());
                return true;
            }

            // 如果存在 则要判断是否需要处理验证码
            if (casCaptchaObj.canLoginWithoutCaptcha()) {
                return true;
            }

            // 验证码不能为空
            if (StringUtil.strIsNullOrEmpty(captcha)) {
                // 设置提示语
                messageContext.addMessage(new MessageBuilder().error().code("screen.cas.userlogin.captcha.validation.empty").build());
                return false;
            }

            // 从session中获取后台生成的验证码
            String serverCaptcha = WebScopeUtil.getCaptchaFromSession(session);
            // 比较验证码
            if (!captcha.equals(serverCaptcha)) {
                messageContext.addMessage(new MessageBuilder().error().code("screen.cas.userlogin.captcha.validation.wrong").build());
                return false;
            }
            return true;
        }
        return false;
    }

    /**
     * . 登陆处理结束之后,根据登陆结果设置验证码判断相关的数据
     * 
     * @param session httpSession
     * @param resultEvent 登陆结果session
     */
    public void captchaValidAfterSubmit(HttpSession session, Event resultEvent) {
        if (session != null) {
            CasLoginCaptchaInfoModel casCaptchaObj = WebScopeUtil.getCaptchaInfoFromSession(session);
            if (casCaptchaObj == null) {
                // 新设置一个
                WebScopeUtil.putCaptchaInfoToSession(session, new CasLoginCaptchaInfoModel());
            }

            // 取出来用
            CasLoginCaptchaInfoModel casLoginCaptcha = WebScopeUtil.getCaptchaInfoFromSession(session);

            // 进行异常类型判断
            if (resultEvent != null) {
                String eventId = resultEvent.getId();
                if (FAILAURE_EVENT_ID_LSIT.contains(eventId)) {
                    // 进行异常处理
                    Object errorObj = resultEvent.getAttributes().get("error");
                    if (errorObj != null) {
                        AuthenticationException e = (AuthenticationException) errorObj;
                        Collection<Class<? extends Exception>> errorClasses = e.getHandlerErrors().values();
                        // 遍历判断是否有需要处理的类型
                        if (errorClasses != null && !errorClasses.isEmpty()) {
                            for (Class<? extends Exception> tclass : errorClasses) {
                                if (FAILAURE_FOCUS_CLASS_LSIT.contains(tclass)) {
                                    // 增加一次失败次数
                                    casLoginCaptcha.failedCountInc();
                                    break;
                                }
                                if (FAILAURE_CLASS_AS_SUCCESS_LSIT.contains(tclass)) {
                                    // 作为登陆成功处理
                                    casLoginCaptcha.reInit();
                                    break;
                                }
                            }
                        }
                    }
                }

                if (SUCCESS_EVENT_ID_LSIT.contains(eventId)) {
                    // 登陆成功 清空异常记录
                    casLoginCaptcha.reInit();
                }
            }
        }
    }
}
